#ifndef AMERICO_VECTOR_OPERATIONS_H_
#define AMERICO_VECTOR_OPERATIONS_H_

#include "Matrix.h"
#include "Vector.h"

template <typename T>
Vector2<T> abs(const Vector2<T> &aVector)
{
	return Vector2<T>(abs(aVector.x), abs(aVector.y));
}

template <typename T>
Vector3<T> abs(const Vector3<T> &aVector)
{
	return Vector3<T>(abs(aVector.x), abs(aVector.y), abs(aVector.z));
}

template <typename T>
Vector2<T> operator+(const int &aValue, const Vector2<T> &aVector)
{
	return Vector2<T>(aVector.x+aValue, aVector.y);
}

template <typename T>
Vector3<T> operator+(const int &aValue, const Vector3<T> &aVector)
{
	return Vector3<T>(aVector.x+aValue, aVector.y, aVector.z);
}

template <typename T>
inline Vector3<T> X(const T &x) { return Vector3<T>(x,0,0); }

template <typename T>
inline Vector3<T> Y(const T &y) { return Vector3<T>(0,y,0); }

template <typename T>
inline Vector3<T> Z(const T &z) { return Vector3<T>(0,0,z); }

template <typename T>
inline Vector3<T> X(const Vector2<T> &v) { return Vector3<T>(v.x,0,0); }

template <typename T>
inline Vector3<T> Y(const Vector2<T> &v) { return Vector3<T>(0,v.y,0); }

template <typename T>
inline Vector3<T> X(const Vector3<T> &v) { return Vector3<T>(v.x,0,0); }

template <typename T>
inline Vector3<T> Y(const Vector3<T> &v) { return Vector3<T>(0,v.y,0); }

template <typename T>
inline Vector3<T> Z(const Vector3<T> &v) { return Vector3<T>(0,0,v.z); }

template <typename T>
inline Vector3<T> XY(const Vector3<T> &v) { return Vector3<T>(v.x,v.y,0); }

template <typename T>
inline Vector3<T> YZ(const Vector3<T> &v) { return Vector3<T>(0,v.y,v.z); }

template <typename T>
inline Vector3<T> XZ(const Vector3<T> &v) { return Vector3<T>(v.x,0,v.z); }

template <typename T>
inline Vector3<T> V(const T &x) { return Vector3<T>(x,0,0); }

template <typename T>
inline Vector3<T> V(const T &x, const T &y) { return Vector3<T>(x,y,0); }

template <typename T>
inline Vector3<T> V(const T &x, const T &y, const T &z) { return Vector3<T>(x,y,z); }

template <typename T>
inline Vector3<T> operator*(const Vector3<T> &aVector, const Matrix33<T> &aMatrix)
{
	return aMatrix * aVector;
}

template <typename T>
inline Vector4<T> operator*(const Vector4<T> &aVector, const Matrix44<T> &aMatrix)
{
	return aMatrix * aVector;
}

template <typename T>
inline Vector3<T> operator*(const Vector3<T> &aVector, const Matrix44<T> &aMatrix)
{
	return Convert(aMatrix * Convert(aVector));
}

template <typename T>
inline Vector3<T> operator*(const Matrix44<T> &aMatrix, const Vector3<T> &aVector)
{
	return Convert(aMatrix * Convert(aVector));
}

template <typename T>
inline Vector2<T> ConvertFrom3To2(const Vector3<T> &aVector)
{
	return Vector2<T>(aVector.x, aVector.z);
}

template <typename T>
inline Vector3<T> ConvertFrom2To3(const Vector2<T> &aVector)
{
	return Vector3<T>(aVector.x, 0, aVector.y);
}

template <typename T>
inline Vector3<T> Convert(const Vector2<T> &aVector)
{
	return Vector3<T>(aVector.x, 0, aVector.y);
}

template <typename T>
inline Vector4<T> Convert(const Vector3<T> &aVector)
{
	return Vector4<T>(aVector.x, aVector.y, aVector.z, 1);
}

template <typename T>
inline Vector4<T> Convert(const Vector3<T> &aVector, const float &aW)
{
	return Vector4<T>(aVector.x, aVector.y, aVector.z, aW);
}

template <typename T>
inline Vector3<T> Convert(const Vector4<T> &aVector)
{
	return Vector3<T>(aVector.x, aVector.y, aVector.z);
}

template <typename T>
inline Vector3<T> GetTranslation(const Matrix44<T> &aMatrix)
{
	return Vector3<T>(aMatrix[12], aMatrix[13], aMatrix[14]);
}

template <typename T>
inline Vector4<T> GetTranslation4(const Matrix44<T> &aMatrix)
{
	return Vector4<T>(aMatrix[12], aMatrix[13], aMatrix[14],  aMatrix[15]);
}

template <typename T>
inline void SetTranslation(Matrix44<T> &aMatrix, const Vector3<T> &aVector)
{
	aMatrix[12] = aVector.x;
	aMatrix[13] = aVector.y;
	aMatrix[14] = aVector.z;
}

template <typename T>
inline void SetTranslation(Matrix44<T> &aMatrix, const Vector4<T> &aVector)
{
	aMatrix[12] = aVector.x;
	aMatrix[13] = aVector.y;
	aMatrix[14] = aVector.z;
}

template <typename T>
inline void SetTranslation4(Matrix44<T> &aMatrix, const Vector4<T> &aVector)
{
	aMatrix[12] = aVector.x;
	aMatrix[13] = aVector.y;
	aMatrix[14] = aVector.z;
	aMatrix[15] = aVector.w;
}
#endif